home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / utility / element2.zip / ELEMENT2.C < prev    next >
C/C++ Source or Header  |  1990-12-27  |  12KB  |  454 lines

  1. //
  2. // Periodic table of the elements, for Microsoft Windows 3.0.
  3. // Originally written by Gregory A. Jones, uunet!microsoft!gregj.
  4. // Modified by Charles L. Perrin to display the name and atomic weight
  5. //     of the element on the fly (in red) and not in a dialog box.
  6. //
  7.  
  8. // This program may be freely distributed.
  9.  
  10. // Chemical data culled from reference works, including the
  11. //    CRC Handbook of Chemistry and Physics.
  12.  
  13. #include <windows.h>
  14.  
  15. //
  16. // Prototypes for exported function.
  17. //
  18.  
  19. long FAR PASCAL WndProc (HWND, unsigned, WORD, LONG);
  20.  
  21. //
  22. // A few global variables.
  23. //
  24.  
  25. char szAppName [] = "PTable2";
  26. char szWorkSpace [80];
  27. HANDLE ghInstance, hWhiteBrush;
  28. int iElementOld;
  29.  
  30. //
  31. // Data stored for each element.  Includes name, symbol, atomic weight,
  32. // and location in table (where period one is row 0, family 1a is column 0).
  33. // Atomic number is implicit, since the table is ordered by it.
  34. //
  35.  
  36. typedef struct tagELEMENT {
  37.     char *pszName;    // Name of the element, i.e. "Hydrogen"
  38.     char *pszSymbol;    // Symbol, i.e. "He"
  39.     char *pszWeight;    // Atomic weight, i.e. "(230)"
  40.     WORD wColumn;    // Column number to draw in
  41.     WORD wRow;        // Row number to draw in
  42. } ELEMENT;
  43.  
  44. typedef ELEMENT *PELEMENT;
  45.  
  46. //
  47. // Width and height of the table, and number of elements defined.
  48. //
  49.  
  50. #define NUM_COLUMNS    18
  51. #define NUM_ROWS    10
  52. #define MAX_ELEMENTS    106
  53.  
  54. //
  55. // Titles for the families, by column.  Null strings are because "8"
  56. // really covers three columns.
  57. //
  58.  
  59. char *pszTitles [NUM_COLUMNS] = {
  60. "1a", "2a", "3b", "4b", "5b", "6b", "7b", "", "8", "", "1b", "2b",
  61. "3a", "4a", "5a", "6a", "7a", "0"
  62. };
  63.  
  64. //
  65. // The elements themselves.  Add new ones on the end if you discover them.
  66. // Also, don't forget to set MAX_ELEMENTS to the new value!
  67. //
  68.  
  69. ELEMENT elTable [MAX_ELEMENTS] = {
  70. "Hydrogen", "H", "1.0079", 0, 0,
  71. "Helium", "He", "4.00260", 17, 0,
  72. "Lithium", "Li", "6.94", 0, 1,
  73. "Beryllium", "Be", "9.01218", 1, 1,
  74. "Boron", "B", "10.81", 12, 1,
  75. "Carbon", "C", "12.011", 13, 1,
  76. "Nitrogen", "N", "14.0067", 14, 1,
  77. "Oxygen", "O", "15.9994", 15, 1,
  78. "Fluorine", "F", "18.998403", 16, 1,
  79. "Neon", "Ne", "20.17", 17, 1,
  80. "Sodium", "Na", "22.98977", 0, 2,
  81. "Magnesium", "Mg", "24.305", 1, 2,
  82. "Aluminum", "Al", "26.98154", 12, 2,
  83. "Silicon", "Si", "28.0855", 13, 2,
  84. "Phosphorous", "P", "30.97376", 14, 2,
  85. "Sulfur", "S", "32.06", 15, 2,
  86. "Chlorine", "Cl", "35.453", 16, 2,
  87. "Argon", "Ar", "39.948", 17, 2,
  88. "Potassium", "K", "39.0983", 0, 3,
  89. "Calcium", "Ca", "40.08", 1, 3,
  90. "Scandium", "Sc", "44.9559", 2, 3,
  91. "Titanium", "Ti", "47.90", 3, 3,
  92. "Vanadium", "V", "50.9415", 4, 3,
  93. "Chromium", "Cr", "51.996", 5, 3,
  94. "Manganese", "Mn", "54.9380", 6, 3,
  95. "Iron", "Fe", "55.847", 7, 3,
  96. "Cobalt", "Co", "58.9332", 8, 3,
  97. "Nickel", "Ni", "58.71", 9, 3,
  98. "Copper", "Cu", "63.546", 10, 3,
  99. "Zinc", "Zn", "65.38", 11, 3,
  100. "Gallium", "Ga", "69.735", 12, 3,
  101. "Germanium", "Ge", "72.59", 13, 3,
  102. "Arsenic", "As", "74.9216", 14, 3,
  103. "Selenium", "Se", "78.96", 15, 3,
  104. "Bromium", "Br", "79.904", 16, 3,
  105. "Krypton", "Kr", "83.80", 17, 3,
  106. "Rubidium", "Rb", "85.467", 0, 4,
  107. "Strontium", "Sr", "87.62", 1, 4,
  108. "Yttrium", "Y", "88.9059", 2, 4,
  109. "Zirconium", "Zr", "91.22", 3, 4,
  110. "Niobium", "Nb", "92.9064", 4, 4,
  111. "Molybdenum", "Mo", "95.94", 5, 4,
  112. "Technetium", "Tc", "98.9062", 6, 4,
  113. "Ruthenium", "Ru", "101.07", 7, 4,
  114. "Rhodium", "Rh", "102.9055", 8, 4,
  115. "Palladium", "Pd", "106.4", 9, 4,
  116. "Silver", "Ag", "107.868", 10, 4,
  117. "Cadmium", "Cd", "112.41", 11, 4,
  118. "Indium", "In", "114.82", 12, 4,
  119. "Tin", "Sn", "118.69", 13, 4,
  120. "Antimony", "Sb", "121.75", 14, 4,
  121. "Tellurium", "Te", "127.60", 15, 4,
  122. "Iodine", "I", "126.9045", 16, 4,
  123. "Xenon", "Xe", "131.30", 17, 4,
  124. "Cesium", "Cs", "132.9054", 0, 5,
  125. "Barium", "Ba", "137.33", 1, 5,
  126. "Lanthanum", "La", "138.9055", 2, 5,
  127. "Cerium", "Ce", "140.12", 2, 8,
  128. "Praeseodymium", "Pr", "140.9077", 3, 8,
  129. "Neodymium", "Nd", "144.24", 4, 8,
  130. "Promethium", "Pm", "(145)", 5, 8,
  131. "Samarium", "Sm", "150.4", 6, 8,
  132. "Europium", "Eu", "151.96", 7, 8,
  133. "Gadolinium", "Gd", "157.25", 8, 8,
  134. "Terbium", "Tb", "158.9254", 9, 8,
  135. "Dysprosium", "Dy", "162.50", 10, 8,
  136. "Holmium", "Ho", "164.9304", 11, 8,
  137. "Erbium", "Er", "167.26", 12, 8,
  138. "Thulium", "Tm", "168.9342", 13, 8,
  139. "Ytterbium", "Yb", "173.04", 14, 8,
  140. "Lutetium", "Lu", "174.96", 15, 8,
  141. "Hafnium", "Hf", "178.49", 3, 5,
  142. "Tantalum", "Ta", "180.947", 4, 5,
  143. "Tungsten", "W", "183.85", 5, 5,
  144. "Rhenium", "Re", "186.207", 6, 5,
  145. "Osmium", "Os", "190.2", 7, 5,
  146. "Iridium", "Ir", "192.22", 8, 5,
  147. "Platinum", "Pt", "195.09", 9, 5,
  148. "Gold", "Au", "196.9665", 10, 5,
  149. "Mercury", "Hg", "200.59", 11, 5,
  150. "Thallium", "Tl", "204.37", 12, 5,
  151. "Lead", "Pb", "207.2", 13, 5,
  152. "Bismuth", "Bi", "208.9804", 14, 5,
  153. "Polonium", "Po", "(209)", 15, 5,
  154. "Astatine", "At", "(210)", 16, 5,
  155. "Radon", "Rn", "(222)", 17, 5,
  156. "Francium", "Fr", "(223)", 0, 6,
  157. "Radium", "Ra", "226.0254", 1, 6,
  158. "Actinium", "Ac", "(227)", 2, 6,
  159. "Thorium", "Th", "232.0381", 2, 9,
  160. "Protactinium", "Pa", "231.0359", 3, 9,
  161. "Uranium", "U", "238.029", 4, 9,
  162. "Neptunium", "Np", "237.0482", 5, 9,
  163. "Plutonium", "Pu", "(244)", 6, 9,
  164. "Americium", "Am", "(243)", 7, 9,
  165. "Curium", "Cm", "(247)", 8, 9,
  166. "Berkelium", "Bk", "(247)", 9, 9,
  167. "Calfornium", "Cf", "(251)", 10, 9,
  168. "Einsteinium", "Es", "(254)", 11, 9,
  169. "Fermium", "Fm", "(257)", 12, 9,
  170. "Mendelevium", "Md", "(258)", 13, 9,
  171. "Nobelium", "No", "(259)", 14, 9,
  172. "Lawrencium", "Lr", "(260)", 15, 9,
  173. "Rutherfordium", "Rf", "(260)", 3, 6,
  174. "Hahnium", "Ha", "(260)", 4, 6,
  175. "Not Named Yet", "106", "(263)", 5, 6
  176. };
  177.  
  178. //
  179. // Main entry point for this application.
  180. //
  181.  
  182. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
  183.             LPSTR lpszCmdLine, int nCmdShow)
  184. {
  185.     HWND hWnd;
  186.     MSG msg;
  187.     WNDCLASS wndclass;
  188.  
  189.     //
  190.     // Save handle instance globally.
  191.     //
  192.  
  193.     ghInstance = hInstance;
  194.  
  195.     //
  196.     // Register the window class for this application.
  197.     //
  198.  
  199.     if (!hPrevInstance) {
  200.     wndclass.style = CS_VREDRAW | CS_HREDRAW;
  201.     wndclass.lpfnWndProc = WndProc;
  202.     wndclass.cbClsExtra = 0;
  203.     wndclass.cbWndExtra = 0;
  204.     wndclass.hInstance = hInstance;
  205.     wndclass.hIcon = LoadIcon (hInstance, "mainicon");
  206.     wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
  207.     wndclass.hbrBackground = GetStockObject (WHITE_BRUSH);
  208.     wndclass.lpszMenuName = NULL;
  209.     wndclass.lpszClassName = szAppName;
  210.  
  211.     if (!RegisterClass (&wndclass))
  212.         return FALSE;
  213.     }
  214.  
  215.     //
  216.     // Create a white background for future use.
  217.     // Crash if we fail to do so.
  218.     //
  219.         
  220.     hWhiteBrush = GetStockObject(WHITE_BRUSH);
  221.     if (!hWhiteBrush)
  222.     return FALSE;
  223.     
  224.     //
  225.     // Set old element number to cause display on first entry.
  226.     //
  227.     
  228.     iElementOld = MAX_ELEMENTS + 1;    
  229.  
  230.     //
  231.     // Create and display the main window.
  232.     //
  233.  
  234.     hWnd = CreateWindow (szAppName, "Periodic Table", WS_OVERLAPPED |
  235.             WS_CAPTION | WS_THICKFRAME | WS_SYSMENU |
  236.             WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
  237.             CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL,
  238.             hInstance, NULL);
  239.  
  240.     ShowWindow (hWnd, nCmdShow);
  241.     UpdateWindow (hWnd);
  242.  
  243.     //
  244.     // The world-famous Microsoft Windows message loop.
  245.     // By the time you get your first WinApp working, you will be seeing
  246.     // messages in your sleep!
  247.     //
  248.  
  249.     while (GetMessage (&msg, NULL, 0, 0)) {
  250.     TranslateMessage (&msg);
  251.     DispatchMessage (&msg);
  252.     }
  253.  
  254.     //
  255.     // Return control to caller (Windows).
  256.     //
  257.  
  258.     return msg.wParam;
  259. }
  260.  
  261. long FAR PASCAL WndProc (HWND hWnd, unsigned iMessage, WORD wParam, LONG lParam)
  262. {
  263.     static WORD cxClient, cyClient, cxBox, cyBox;
  264.     int i, cyChar, xBox, yBox;
  265.     PAINTSTRUCT ps;
  266.     HDC hDC;
  267.     PELEMENT pel;
  268.     char buf [10];
  269.     RECT rect;
  270.  
  271.     switch (iMessage) {
  272.     case WM_SIZE:
  273.  
  274.         //
  275.         // When the window changes size, update static variables
  276.         // containing the window size and size of each box.
  277.         //
  278.  
  279.         cxClient = LOWORD (lParam);
  280.         cyClient = HIWORD (lParam);
  281.         cxBox = (cxClient - 40) / NUM_COLUMNS;
  282.         cyBox = (cyClient - 60) / NUM_ROWS;
  283.         break;
  284.  
  285.     case WM_MOUSEMOVE:
  286.  
  287.         //
  288.         // Mouse motion has occurred.  Where is that dirty rat?
  289.         //
  290.     
  291.         //
  292.         // Convert the mouse location to a corresponding element box.
  293.         //
  294.  
  295.         xBox = (LOWORD (lParam) - 20) / cxBox;
  296.         yBox = (HIWORD (lParam) - 40) / cyBox;
  297.  
  298.         //    
  299.         // Scan the element table to determine which box holds the mouse.
  300.         //
  301.  
  302.         for (i=0; i<MAX_ELEMENTS; i++)
  303.         if (elTable [i].wColumn == xBox &&
  304.             elTable [i].wRow == yBox)
  305.             break;
  306.  
  307.         //
  308.         // Did the element number change?
  309.         //
  310.  
  311.         if (i != iElementOld) {
  312.  
  313.         //
  314.         // Save the old element number.
  315.         //
  316.     
  317.         iElementOld = i;
  318.  
  319.         //
  320.         // Build a string to indicate which element is selected.
  321.         //
  322.  
  323.         if (i < MAX_ELEMENTS)
  324.         wsprintf(szWorkSpace,"Element %u - %s(%s) - Atomic Weight %s",i+1,
  325.                     (LPSTR)elTable[i].pszName,
  326.             (LPSTR)elTable[i].pszSymbol,
  327.                     (LPSTR)elTable[i].pszWeight);
  328.         else
  329.         wsprintf(szWorkSpace,"%s",(LPSTR)"HINT:  Point at an element with the mouse.");
  330.                  
  331.         //
  332.         // Get control of the display context.
  333.         //
  334.             
  335.         hDC = GetDC(hWnd);
  336.     
  337.         // 
  338.             // Calculate bounding box for the DrawText operation (the area that is
  339.         // between Hydrogen and Helium with a 1-pixel border).
  340.             //
  341.  
  342.         rect.left = ( elTable[0].wColumn + 1 ) * cxBox + 21;
  343.         rect.right = elTable[1].wColumn * cxBox + 19;
  344.         rect.top = elTable[0].wRow  * cyBox + 40;
  345.         rect.bottom = rect.top + cyBox - 1;
  346.  
  347.         // 
  348.             // Switch text color to red.
  349.             //
  350.     
  351.         SetTextColor(hDC, RGB(255,0,0));
  352.     
  353.             //
  354.             // Fill the element text area with the background.
  355.         //
  356.  
  357.         FillRect(hDC,&rect,hWhiteBrush);
  358.  
  359.         //
  360.         // Display the element text, clipped, centered.
  361.         //
  362.     
  363.         DrawText(hDC,szWorkSpace,-1,&rect,
  364.         DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE );
  365.         
  366.         //    
  367.         // Switch text color back to black.
  368.         //
  369.         
  370.         SetTextColor(hDC,RGB(0,0,0));
  371.  
  372.         //
  373.         // Release display context for other uses.
  374.         //
  375.  
  376.         ReleaseDC(hWnd, hDC);
  377.  
  378.             } // Element changed branch exit at this point.
  379.              
  380.         return 0L;
  381.  
  382.     case WM_PAINT:
  383.  
  384.         //
  385.         // Need to redraw the window from scratch.
  386.         //
  387.  
  388.         hDC = BeginPaint (hWnd, &ps);
  389.         cyChar = HIWORD (GetTextExtent (hDC, "M", 1));
  390.  
  391.         rect.top = cyChar;
  392.         rect.bottom = cyChar * 2 + 2;
  393.  
  394.         //
  395.         // Draw the column titles.
  396.         //
  397.         for (i=0; i<NUM_COLUMNS; i++) {
  398.         rect.left = i * cxBox + 20;
  399.         rect.right = rect.left + cxBox;
  400.         DrawText (hDC, pszTitles [i], -1, &rect, DT_CENTER | DT_VCENTER |
  401.             DT_NOPREFIX | DT_SINGLELINE);
  402.         }
  403.  
  404.         //
  405.         // Now draw each element.  Each one consists of a rectangle to
  406.         // contain the information, the atomic number in the upper left
  407.         // corner, and the atomic symbol centered.
  408.         //
  409.         for (i=0; i<MAX_ELEMENTS; i++) {
  410.         pel = &elTable [i];
  411.         rect.left = pel->wColumn * cxBox + 20;
  412.         rect.right = rect.left + cxBox;
  413.         rect.top = pel->wRow * cyBox + 40;
  414.         rect.bottom = rect.top + cyBox;
  415.         Rectangle (hDC, rect.left, rect.top, rect.right, rect.bottom);
  416.  
  417.         wsprintf (buf, "%i", i+1);
  418.         TextOut (hDC, rect.left+1, rect.top+1, buf, lstrlen (buf));
  419.  
  420.         rect.top += cyChar + 1;
  421.  
  422.         DrawText (hDC, pel->pszSymbol, -1, &rect, DT_CENTER | DT_VCENTER |
  423.             DT_NOPREFIX | DT_SINGLELINE);
  424.         }
  425.  
  426.         EndPaint (hWnd, &ps);
  427.  
  428.         //
  429.             // This assignment forces a position display.
  430.         //
  431.  
  432.             iElementOld = MAX_ELEMENTS + 1;                
  433.  
  434.         //
  435.         // Simulate a mouse motion; where is not germane.
  436.             //
  437.  
  438.         PostMessage(hWnd,WM_MOUSEMOVE,0,0);
  439.  
  440.         return 0L;
  441.  
  442.     case WM_DESTROY:
  443.  
  444.         //
  445.         // Main window closed.  Quit the program.
  446.         //
  447.  
  448.         PostQuitMessage (0);
  449.         return 0L;
  450.     }
  451.  
  452.     return DefWindowProc (hWnd, iMessage, wParam, lParam);
  453. }
  454.